package cn.genmer.test.security.rpc.v2.rpc.transport;

import cn.genmer.test.security.rpc.SerialUtil;
import cn.genmer.test.security.rpc.v2.rpc.Dispatcher;
import cn.genmer.test.security.rpc.v2.rpc.protocol.GContent;
import cn.genmer.test.security.rpc.v2.rpc.protocol.GHeader;
import cn.genmer.test.security.rpc.v2.rpc.protocol.GPackmsg;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.lang.reflect.Method;

public class GServerRequestHandler extends ChannelInboundHandlerAdapter {

    private Dispatcher dispatcher;

    public GServerRequestHandler(Dispatcher dispatcher){
        this.dispatcher = dispatcher;
    }

    // provider
    // 存在一个bytebuf，会传输多个数据（可能不完整），导致下次接收剩下数据序列号出错 - 我没复现，我这都只接收一个
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        GPackmsg requestPkg = (GPackmsg) msg;
        // 假设处理完了，要给客户端返回了(返回的肯定是bytebuf )
        // 因为是RPC框架，需要返回到对应RequestID的客户端，但是多线程已经分不清了
        // IO是双向的，在client也要解码 问题


        // 关注RPC通信协议 来的时候flag是0x14141414 去的时候可能激素0x1515151515 可以定义很多不太的类型代表什么意思

        // 需要新的header + content

        // 当前可以只是IO线程，不涉及业务
        // 1.在当前方法 处理IO和业务、返回
        // 2.使用netty自己的eventLoop来处理业务和返回(eventLoop第三步 runAllTask) | 优化后 就是扔给其他eventLoop执行
        String ioThreadName = Thread.currentThread().getName();
//        ctx.executor().execute(new Runnable() {
        ctx.executor().parent().next().execute(new Runnable() {
            @Override
            public void run() {
                String serviceName = requestPkg.getContent().getName();
                String methodName = requestPkg.getContent().getMethodName();
                Object res = null;
                try{
                    Object obj = dispatcher.get(serviceName);
                    Class<?> clazz = obj.getClass();
                    Method method = clazz.getMethod(methodName, requestPkg.getContent().getParameterTypes());
                    res = method.invoke(obj,requestPkg.getContent().getArgs());
                }catch (Exception e){
                    e.printStackTrace();
                }

                String execThreadName = Thread.currentThread().getName();
                GContent responseContent = new GContent();
                // 设置返回信息
//                StrBuilder strBuilder = new StrBuilder();
//                strBuilder.append("IO线程： ").append(ioThreadName).append(" | 执行线程： ").append(execThreadName).append(" | 调用参数: ").append(requestPkg.content.getArgs()[0]);
                responseContent.setRes((Object) res);
                byte[] contentByte = SerialUtil.serialObject(responseContent);

               GHeader responseHeader = new GHeader();
                responseHeader.setRequestId(requestPkg.getHeader().getRequestId());
                responseHeader.setFlag(GCommonDecode.CLIENT_FLAG);
                responseHeader.setDataLength(contentByte.length);
                byte[] headerByte = SerialUtil.serialObject(responseHeader);
                ByteBuf responseByte = PooledByteBufAllocator.DEFAULT.directBuffer(headerByte.length + contentByte.length);
                responseByte.writeBytes(headerByte);
                responseByte.writeBytes(contentByte);

                ctx.writeAndFlush(responseByte);
            }
        });

    }
}